package com.atguigu.gmall.order.listener;
import java.math.BigDecimal;
import java.util.Date;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.atguigu.gmall.common.config.rabbitMq.MqService;
import com.atguigu.gmall.common.constant.MqConst;

import com.atguigu.gmall.mq.ware.WareStock;
import com.atguigu.gmall.order.biz.OrderBizService;
import com.atguigu.gmall.order.entity.OrderDetail;
import com.atguigu.gmall.order.entity.OrderInfo;
import com.atguigu.gmall.order.entity.PaymentInfo;
import com.atguigu.gmall.order.service.OrderDetailService;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.atguigu.gmall.order.service.PaymentInfoService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class OrderPayedListener {
    @Autowired
    MqService mqService;
    @Autowired
    OrderBizService orderBizService;
    @Autowired
    OrderInfoService  orderInfoService;
    @Autowired
    PaymentInfoService  paymentInfoService;
    @Autowired
    OrderDetailService  detailService;

    /**
     * 监听所以成功单队列
     */
    @RabbitListener(queues = MqConst.ORDER_PAYED_QUEUE)
    public void listen(Message message, Channel channel) throws IOException {
        long tag = message.getMessageProperties().getDeliveryTag();
        String json = new String(message.getBody());
        try{
            log.info("获取消息的内容");
            //TODO 得到的消息内容
            Map<String, String> content = JSON.parseObject(json, new TypeReference<Map<String, String>>() {
            });

            log.info("修改订单状态为已支付");
            //订单对外唯一交易号
            String out_trade_no = content.get("out_trade_no");
            String[] split = out_trade_no.split("-");
            long userId = Long.parseLong(split[split.length - 1]);
            //todo 根据唯一的订单交易号 和用户id 修改订单状态
            orderBizService.updateOrderStatus(out_trade_no,userId);

            //TODO 保存此支付回调的数据信息 在 paymeninfo
            PaymentInfo info = prepareInfo(json, content, out_trade_no, userId);
            paymentInfoService.save(info);
            //TODO 怎样实现支付后锁定库存  通过发送消息通知库存系统 扣减库存
            WareStock  stock= prepareWareStockMsg(out_trade_no,userId);
            mqService.send(stock,MqConst.WARE_STOCK_EXCHANGE,MqConst.WARE_STOCK_RK);

            channel.basicAck(tag,false);
        }catch (Exception e){
            //失败重复五次
            mqService.retry(channel,tag,json,5);


        }

    }

    private WareStock prepareWareStockMsg(String out_trade_no, long userId) {
        OrderInfo orderInfo = orderInfoService.lambdaQuery()
                .eq(OrderInfo::getOutTradeNo, out_trade_no)
                .eq(OrderInfo::getUserId, userId)
                .one();
        WareStock wareStock = new WareStock();
        //TODO 1 订单的基本信息
        wareStock.setOrderId(orderInfo.getId());
        wareStock.setUserId(orderInfo.getUserId());
        wareStock.setConsigee(orderInfo.getConsignee());
        wareStock.setConsigneeTel(orderInfo.getConsigneeTel());
        wareStock.setOrderComment(orderInfo.getOrderComment());
        wareStock.setOrderBody(orderInfo.getTradeBody());
        wareStock.setDriverAddress(orderInfo.getDeliveryAddress());
        wareStock.setPaymentWay("2");
        //TODO 订单的明细
        List<OrderDetail> orderDetails = detailService.lambdaQuery()
                .eq(OrderDetail::getOrderId, orderInfo.getId())
                .eq(OrderDetail::getUserId, orderInfo.getUserId())
                .list();
        List<WareStock.Sku> skuList = orderDetails.stream()
                .map(item ->
                {
                    WareStock.Sku sku = new WareStock.Sku();
                    sku.setSkuId(item.getSkuId());
                    sku.setSkuNum(item.getSkuNum());
                    sku.setSkuName(item.getSkuName());
                    return sku;
                }).collect(Collectors.toList());

        wareStock.setDetails(skuList);

     return  wareStock;

    }

    private PaymentInfo prepareInfo(String json, Map<String, String> content, String out_trade_no, long userId) {
        OrderInfo orderInfo = orderInfoService.lambdaQuery()
                .eq(OrderInfo::getUserId, userId)
                .eq(OrderInfo::getOutTradeNo, out_trade_no)
                .one();
        PaymentInfo  paymentInfo =new PaymentInfo();
        paymentInfo.setId(0);
        paymentInfo.setUserId(userId);
        paymentInfo.setOutTradeNo(out_trade_no);
        paymentInfo.setOrderId(orderInfo.getId());
        paymentInfo.setPaymentType(orderInfo.getPaymentWay());
        String trade_no = content.get("trade_no");
        paymentInfo.setTradeNo(trade_no);
        String total_amount = content.get("total_amount");
        paymentInfo.setTotalAmount(new BigDecimal(total_amount));
        paymentInfo.setSubject(content.get("subject"));
        paymentInfo.setPaymentStatus(content.get("trade_status"));
        paymentInfo.setCreateTime(new Date());
        paymentInfo.setCallbackTime(new Date());
        paymentInfo.setCallbackContent(json);
        return paymentInfo;
    }
}
